<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<a href="https://juejin.cn/post/7000995991927144479">知乎文章</a>
		<script type="module">
			import '../lib/js/face-api.min.js';
			import { loadRandomImage } from "../lib/js/util.js";
			(async function() {
				await faceapi.nets.faceLandmark68Net.loadFromUri('../models');
				await faceapi.nets.ssdMobilenetv1.loadFromUri('../models');
				
				const image = await loadRandomImage();
				document.body.append(image);
				// 获取脸部坐标
				const faces = await faceapi.detectAllFaces(image).withFaceLandmarks();
				
				// 设置眼睛盒子大小
				function getBoxFromPoints(points) {
				  const box = {
				    bottom: -Infinity,
				    left: Infinity,
				    right: -Infinity,
				    top: Infinity,
				
				    get center() {
				      return {
				        x: this.left + this.width / 2,
				        y: this.top + this.height / 2,
				      };
				    },
				
				    get height() {
				      return this.bottom - this.top;
				    },
				
				    get width() {
				      return this.right - this.left;
				    },
				  };
				
				  for (const point of points) {
				    box.left = Math.min(box.left, point.x);
				    box.right = Math.max(box.right, point.x);
				
				    box.bottom = Math.max(box.bottom, point.y);
				    box.top = Math.min(box.top, point.y);
				  }
				
				  return box;
				}
				
				// 显示到页面
				const canvas = document.createElement('canvas');
				const context = canvas.getContext('2d');
				canvas.height = image.naturalHeight;
				canvas.width = image.naturalWidth;
				context.drawImage(image, 0, 0);

				// 除了脸部的位置外，每个结果还包含一个地标的原始点列表。为了得到每个特征的正确地标，我们需要对点的列表进行切片。因为点的数量是固定的，所以我选择了硬编码的索引。
				for (const face of faces) {
					const features = {
						jaw: face.landmarks.positions.slice(0, 17),
						eyebrowLeft: face.landmarks.positions.slice(17, 22),
						eyebrowRight: face.landmarks.positions.slice(22, 27),
						noseBridge: face.landmarks.positions.slice(27, 31),
						nose: face.landmarks.positions.slice(31, 36),
						eyeLeft: face.landmarks.positions.slice(36, 42),
						eyeRight: face.landmarks.positions.slice(42, 48),
						lipOuter: face.landmarks.positions.slice(48, 60),
						lipInner: face.landmarks.positions.slice(60),
					};
			
					for (const eye of [features.eyeLeft, features.eyeRight]) {
						const eyeBox = getBoxFromPoints(eye);
						const fontSize = 6 * eyeBox.height;
			
						context.font = `${fontSize}px/${fontSize}px serif`;
						context.textAlign = 'center';
						context.textBaseline = 'bottom';
			
						context.fillStyle = '#000';
						context.fillText('👁️', eyeBox.center.x, eyeBox.center.y + 0.6 * fontSize);
					}
				}
				
				
				document.body.append(canvas);
			})();
		</script>
	</body>
</html>